import 'package:flutter_test/flutter_test.dart';

//单行注释
/**
 * 多行注释
 */

///
///
///文档注释
///
void main() {
  test("testNumber", () {
    //-2^63 到 2^63 - 1，Dart 被编译为 JavaScript 时，使用 JavaScript numbers, 值的范围从 -2^53 到 2^53 - 1.
    int a = 1;
    num a1 = 1;
    print("a==a1? ${a == a1}");
    print("a1.runtimeType is ${a1.runtimeType}");

    //基本类型没有long
    var a2 = BigInt.from(1);
    print("a==a2? ${a == a2}");

    //如果长度过长会报错
//    var a3 = 2132323232332322332323;
    var a3 = BigInt.parse("2132323232332322332323");
    print("a3 is $a3");

    double b = 1.043434343434;
    print("b.runtimeType is ${b.runtimeType}");

    var c = true;
    print("c.runtimeType is ${c.runtimeType}");
    String d = "abc";

    dynamic g = 1;
    print("g.runtimeType1 is ${g.runtimeType}");
    //但是这样的坏处就是会让dart的语法检查失效，所以有可能会造成混乱而不报错
    g = 1.0;
    print("g.runtimeType2 is ${g.runtimeType}");
    g = "asdfd";
    print("g.runtimeType3 is ${g.runtimeType}");
    print("$g");
    //静态类型检查不报错，但是实际运行会崩溃
//    g.test();

    Object e = 1;
    print("e.runtimeType is ${e.runtimeType}");
    e = 1.0;
    print("e.runtimeType is ${e.runtimeType}");
    //静态类型检查出错
//    e.test();

    var f = 1;
    //var定义的类型是不可变的，dynamic和object类型是可以变的，而dynamic 与object 的最大的区别是在静态类型检查上
    //f = 1.0;
    print("f.runtimeType is ${f.runtimeType}");

    int h;
//    未初始化的变量默认值是 null。即使变量是数字 类型默认值也是 null，因为在 Dart 中一切都是对象，数字类型 也不例外
    print("h.runtimeType is ${h.runtimeType}");
    h = 3;
    print("h.runtimeType is ${h.runtimeType}");
  });

  test("testString", () {
    //字符串可以用单引号或双引号
    //字符串中也是可以像kotlin一样用${expression}(无论单引号还是双引号都可以)，
    var s = 'string interpolation';
    assert('Dart has $s, which is very handy.' ==
        'Dart has string interpolation, ' + 'which is very handy.');

    //使用连续三个单引号或者三个双引号实现多行字符串对象的创建：
    var s1 = '''
You can create
multi-line strings like this one.
''';
    print(s1);

    //使用 r 前缀，可以创建 “原始 raw” 字符串
    var s2 = r"In a raw string, even \n isn't special.";
    print(s2);
  });

  //final类型的只能被设置一次，有点像kotlin的val
  test("testFinalAndConst", () {
    //类型可以写也可以不写
    final String name = "abc";
    final name1 = "abc";

    const name2 = "ggg";

    //final和const的区别在类里体现
    FinalTest("abc");
  });

  test("testList", () {
//Dart 中的 Array 就是 List
    var list = [1, 2, 3];
    list[1] = 33;

    var list2 = const [1, 2, 3];
    // 取消注释会引起错误
//    list2[1] = 33;

    var list3 = new List(4);
    //长度固定的list不允许改变
//    list3.length=5;
    print("list3 length is ${list3.length}");
//    list3.add(1);
//    print(list3);

    //一开始长度为0的list为可变长度list
    List growableList = new List()..length = 5;
    growableList.length = 54;
    print("growableList length is ${growableList.length}");
  });

  test("testSet", () {
    //Dart 2.2 以上才支持
    var set = {'a', "b", "a", "c"};
    print("set size is ${set.length}");
    set.forEach((value){
      print("value is $value");
    });
  });

  test("testMap", () {
    var gifts = {
      // Key:    Value
      'first': 'partridge',
      'second': 'turtledoves',
      'fifth': 'golden rings'
    };
    print("gifts is $gifts");

    final constantMap = const {
      2: 'helium',
      10: 'neon',
      18: 'argon',
    };
// constantMap[2] = 'Helium'; // 取消注释会引起错误。
    constantMap.forEach((k,v) => print('$k: $v'));

  });

  test("testOther", () {
    var clapping = "\u2665";
    print(clapping);
    print(clapping.codeUnits);
    print(clapping.runes.toList());

    var clapping2 = '\u{1f44f}\u{1e44f}';
    print(clapping2);
    print(clapping2.codeUnits);
    print(clapping2.runes.toList());

    //Rune 用来表示字符串中的 UTF-32 编码字符
    Runes input = new Runes(
        '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
    print(new String.fromCharCodes(input));

    ///Symbol对象表示在Dart程序中声明的运算符或标识符。您可能永远不需要使用符号，
    ///但它们对于按名称引用标识符的API非常有用，因为缩小会更改标识符名称而不会更改标识符符号。
    ///要获取标识符的符号，请使用符号文字，它只是＃后跟标识符
    assert(new Symbol("foo") == #foo);
    assert(new Symbol("[]=") == #[]=);
    assert(new Symbol("foo.bar") == #foo.bar);
    assert(identical(const Symbol("foo"), #foo));
    assert(identical(const Symbol("[]="), #[]=));
    assert(identical(const Symbol("foo.bar"), #foo.bar));
  });
}

///使用过程中从来不会被修改的变量， 可以使用 final 或 const, 而不是 var 或者其他类型， Final 变量的值只能被设置一次；
/// Const 变量在编译时就已经固定 (Const 变量 是隐式 Final 的类型.) 最高级 final 变量或类变量在第一次使用时被初始化。
class FinalTest {
  final name;

  //在类里面的const必须是static
  static const age = 3;

  //以下会报错
  //const name2 = "asdf";

  //final的类型必须在构造函数内赋值
  FinalTest(this.name);
}
